package model;

import java.util.ArrayList;
import java.util.HashMap;

import processing.core.PVector;

import viz_main.ScatterPlotCAxis;

// TODO: parsing/formatting dates:
// SimpleDateFormat and DateFormat classes


public class DataHandler {
	private final String DATASET = ".//data//Parking_LARGE.csv";
	//private final String DATASET = ".//data//Parking_FirstThreeMonths.csv";
	private final PVector RANGE = new PVector(0, 12); // only parse within this range of columns, ignore others
	private final float SAMPLE_INTERVAL = 3; // use this variable to sample only a sub-set of the data at even intervals
	  										 // GREATLY REDUCES PARSE TIME!!	
	private HashMap<String, ScatterPlotCAxis> cAxisList;
	private String labels[];
	private int totalRecords;
	
	public DataHandler()
	{ 
		
	}

  // This is the method for parsing out the data from the CSV file and converting it into ScatterPlotAxis(plural)
  // TODO: We'll probably want to move this to a separate set of model classes that handle the data and 
  // separate it even further from the view. Also, we'll need to parse both XML and CSV
  
  //TODO: there is an error with the data parsing. It seems to be adding a few values from the 
  //	previous index to the new array. That is very strange!
  public void parseCSV()
  {
    cAxisList = new HashMap<String, ScatterPlotCAxis>(); // new code!
	  
	String lines[] = ModelUtilities.ReadFile( DATASET );
    System.out.println("there are " + lines.length + " lines");
    totalRecords = lines.length-1;
   
    // Run through the first 2 lines of the data set to set up the initial data structure:
    String[] tempList = lines[0].split(","); // split the values into an array using comma as a separator
    // only include the labels for things we've actually included in our range:
    labels = new String[(int) (RANGE.y - RANGE.x)];
    int count = 0;
    for(int i = (int) RANGE.x; i < (int) RANGE.y; i++)
    {
    	labels[count] = tempList[i];
    	count++;
    }
    
    //String[] row_1 = split( lines[1], "," ); // get the next line's values
    for(int i = 0; i < labels.length; i++)
    {
      // create a cAxis for every column
      cAxisList.put(labels[i], new ScatterPlotCAxis(labels[i], totalRecords));
    }
    
    // Run through the entire data set (every line):
    //System.out.println(values.length + " :values | labels: " + labels.length);
    for (int i=1; i < lines.length ; i++ ) 
    {
      if (lines[i] != null)
      {
	      String[] values = lines[i].split(","); // split the values into an array using comma as a separator (every value)
	      
	      // Parse only the elements within our specified range:
	      // also only parse up until the amount of LABELED data (although values should theoretically have the same number of elements
	      // it occasionally has 1 additional empty element that has no associated label.
	      
	      count = 0; // need to use this counter to accurately map the data when using our RANGE thinger
	      			 // ( because j doesn't necessarily start at 0)
	      for( int j = (int)RANGE.x ; j < (int)RANGE.y; j++ )
	      {  
	    	//System.out.println(labels[j]);
	    	//System.out.println("[" + labels[j] + "]" + values[j]);
	    	cAxisList.get(labels[count]).addElement(values[j], i-1);  
	    	count ++;  
	      }
		  i += SAMPLE_INTERVAL; // increase index "i" faster than 1 if SAMPLE_INTERVAL > 0
      }
    } // End of for-loop
    
    // USE THE FOLLOWING TO TEST THE CONTENTS OF ONE OF THE DATAOBJECTS: (change index to check different axis)
    //cAxisList.get("Block").printContents();
    
    // Preform a numerical sort on the times by converting them to integers
    sortByNumber("Time");
  }
  
  public void sortByNumber(String label)
  {
	  ScatterPlotCAxis curAxis = getAttributeAxis(label);
	  ArrayList<String> categoriesMap = curAxis.getUniqueCategories();
	  categoriesMap = sortCategories(categoriesMap);
	  curAxis.setUniqueCategories(categoriesMap);
  }
  
  public static ArrayList<String> sortCategories(ArrayList<String> events)
	{
		ArrayList<String> tmpList = new ArrayList<String>();
		if(events.size() <= 1)
		{
			return events;
		}
		int pivotIndex = events.size()/2;
		String pivot = events.get(pivotIndex);
		ArrayList<String> less = new ArrayList<String>();
		ArrayList<String> greater = new ArrayList<String>();
		for(int i = 0; i < events.size(); i++)
		{
			if(i != pivotIndex)
			{
				if(Integer.parseInt(events.get(i)) <= Integer.parseInt(pivot))
				{
					less.add(events.get(i));
				}
				else
				{
					greater.add(events.get(i));
				}
			}
		}
		tmpList.addAll(sortCategories(less)); // recursively sort the less list;
		tmpList.add(pivot);
		tmpList.addAll(sortCategories(greater)); // recursively sort the greater list;
		return tmpList;
	}
  
  
   // use this method to get the list of all categorical axis:
   public HashMap<String, ScatterPlotCAxis> getCAxisList()
   {
	   return cAxisList;
   }
   
   // get a specific axis from the list, by its name
   public ScatterPlotCAxis getAttributeAxis(String label)
   {
	   return cAxisList.get(label);
   }
   
	// get a specific axis from the list, by its column index
   public ScatterPlotCAxis getAttributeAxis(int columnNumber)
   {
	   return cAxisList.get(labels[columnNumber]);
   }
	
   // get the label for each column
	public String[] getLabels(){
		return labels;
	}
	
}
